home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Extras / Networking / SANA-II / slip_src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-06  |  60.0 KB  |  1,999 lines

  1. /*
  2. ** $Id: main.c,v 38.1 94/02/17 14:13:56 kcd Exp $
  3. ** $State: Exp $
  4. ** $Revision: 38.1 $
  5. ** $Date: 94/02/17 14:13:56 $
  6. ** $Author: kcd $
  7. **
  8. ** Amiga SANA-II SLIP device driver.
  9. **
  10. ** (C) Copyright 1992-1998 Amiga, Inc.
  11. **
  12. ** OwnDevUnit support added by Christopher A. Wichura.
  13. */
  14.  
  15. #include "slip_device.h"
  16.  
  17. #include <dos/dostags.h>
  18. #include <dos/rdargs.h>
  19.  
  20. #include <clib/exec_protos.h>
  21. #include <clib/dos_protos.h>
  22. #include <clib/utility_protos.h>
  23. #include <clib/timer_protos.h>
  24. #include <clib/alib_stdio_protos.h>
  25. #include <clib/intuition_protos.h>
  26.  
  27. #include <pragmas/exec_pragmas.h>
  28. #include <pragmas/dos_pragmas.h>
  29. #include <pragmas/utility_pragmas.h>
  30. #include <pragmas/timer_pragmas.h>
  31. #include <pragmas/intuition_pragmas.h>
  32.  
  33. #include <string.h>
  34.  
  35. #ifndef _GENPROTO
  36. #include "main_protos.h"
  37. #include "slcompress_protos.h"
  38. #endif
  39.  
  40. /*
  41. ** To Do:
  42. **
  43. **     Try using an address field size of 0.
  44. **
  45. ** For speed purposes:
  46. **
  47. **     Downcode the packet encode/decode routines.
  48. */
  49.  
  50. /*
  51. ** External variables and functions
  52. **
  53. */
  54.  
  55. extern struct Library *ExtDeviceBase;
  56. extern VOID (*DevProcEntry)();
  57. extern ULONG IPToNum(STRPTR ipstr);
  58.  
  59. /*
  60. ** Device Open vector
  61. **
  62. ** a1 - SANA2 IO Request
  63. ** a6 - Pointer to our device base
  64. ** d0 - Unit number
  65. ** d1 - Flags
  66. **
  67. */
  68.  
  69. ULONG ASM DevOpen(REG(a1) struct IOSana2Req *ios2,
  70.                   REG(d0) ULONG s2unit,
  71.                   REG(d1) ULONG s2flags,
  72.                   REG(a6) struct SLIPDevice *slipDevice)
  73. {
  74.     struct SLIPUnit *slipUnit;
  75.     struct TagItem *bufftag;
  76.     struct Library *UtilityBase;
  77.     struct BufferManagement *bm;
  78.     ULONG returncode;
  79.     BOOL status = FALSE;
  80.  
  81.     slipDevice->sd_Device.lib_OpenCnt++;        /* So we won't expunge ourselves... */
  82.  
  83.     /* Make sure our open remains single-threaded. */
  84.     ObtainSemaphore(&slipDevice->sd_Lock);      /* Enforce single threading since we may need to
  85.                                                    Wait() when starting up the Unit process */
  86.  
  87.     if(s2unit < SD_MAXUNITS)    /* Legal Unit? */
  88.     {
  89.         if(slipUnit = InitSLIPUnit(s2unit,slipDevice))     /* Initialize the Unit */
  90.         {
  91.             if(UtilityBase = OpenLibrary("utility.library",37L)) /* For Tag functions */
  92.             {
  93.                 /* Allocate a structure to store the pointers to the callback routines. */
  94.  
  95.                 if(bm = AllocMem(sizeof(struct BufferManagement),MEMF_CLEAR|MEMF_PUBLIC))
  96.                 {
  97.                     /* Note: I don't complain if I can't find pointers to the callback routines.
  98.                              This is because there are some programs that may need to open me, but
  99.                              will never use any device commands that require the callbacks. */
  100.  
  101.                     if(bufftag = FindTagItem(S2_CopyToBuff, (struct TagItem *)ios2->ios2_BufferManagement))
  102.                     {
  103.                         bm->bm_CopyToBuffer = (SANA2_CTB) bufftag->ti_Data;
  104.                     }
  105.  
  106.                     if(bufftag = FindTagItem(S2_CopyFromBuff, (struct TagItem *)ios2->ios2_BufferManagement))
  107.                     {
  108.                         bm->bm_CopyFromBuffer = (SANA2_CFB) bufftag->ti_Data;
  109.                     }
  110.  
  111.                     /* New SANA-II V2 Addition */
  112.                     if(bufftag = FindTagItem(S2_PacketFilter, (struct TagItem *)ios2->ios2_BufferManagement))
  113.                     {
  114.                         bm->bm_PacketFilterHook = (struct Hook *) bufftag->ti_Data;
  115.                     }
  116.                     else /* For backwards compatibility */
  117.                     {
  118.                         bm->bm_PacketFilterHook = &slipDevice->sd_DummyPFHook;
  119.                     }
  120.  
  121.                     /* Init the list for CMD_READ requests */
  122.  
  123.                     NewList((struct List *)&bm->bm_RxQueue);
  124.  
  125.                     AddTail((struct List *)&slipUnit->su_BuffMgmt,(struct Node *)bm);
  126.  
  127.                     /* Everything went okay. */
  128.                     status = TRUE;
  129.                     returncode = 0;
  130.                     slipDevice->sd_Device.lib_OpenCnt++;
  131.                     slipDevice->sd_Device.lib_Flags &=~LIBF_DELEXP;
  132.                     slipUnit->su_Unit.unit_OpenCnt++;
  133.  
  134.                     /* Fix up the initial io request */
  135.                     ios2->ios2_BufferManagement = (void *)bm;
  136.                     ios2->ios2_Req.io_Error = 0;
  137.                     ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  138.                     ios2->ios2_Req.io_Unit = (struct Unit *)slipUnit;
  139.                     ios2->ios2_Req.io_Device = (struct Device *)slipDevice;
  140.                 }
  141.                 CloseLibrary(UtilityBase);
  142.             }
  143.         }
  144.     }
  145.     /* See if something went wrong. */
  146.     if(!status)
  147.     {
  148.         ios2->ios2_Req.io_Error = IOERR_OPENFAIL;
  149.         ios2->ios2_Req.io_Unit = (struct Unit *) -1;
  150.         ios2->ios2_Req.io_Device = (struct Device *) -1;
  151.         returncode = IOERR_OPENFAIL;
  152.     }
  153.     ReleaseSemaphore(&slipDevice->sd_Lock);
  154.     slipDevice->sd_Device.lib_OpenCnt--;
  155.  
  156.     return(returncode);
  157. }
  158.  
  159. /*
  160. ** Device Close vector.
  161. **
  162. ** a1 - IOReq
  163. ** a6 - Device Pointer
  164. **
  165. */
  166.  
  167. BPTR ASM DevClose(REG(a1) struct IOSana2Req *ios2,
  168.                   REG(a6) struct SLIPDevice *slipDevice)
  169. {
  170.     struct SLIPUnit *slipUnit;
  171.     BPTR seglist = 0L;
  172.  
  173.     ObtainSemaphore(&slipDevice->sd_Lock);
  174.  
  175.     slipUnit    = (struct SLIPUnit *)ios2->ios2_Req.io_Unit;
  176.  
  177.     /* Trash the io_Device and io_Unit fields so that any attempt to use this
  178.        request will die immediatly. */
  179.  
  180.     ios2->ios2_Req.io_Device = (struct Device *) -1;
  181.     ios2->ios2_Req.io_Unit = (struct Unit *) -1;
  182.  
  183.     /* I always shut the unit process down if the open count drops to zero.
  184.        That way, if I need to expunge, I never have to Wait(). */
  185.  
  186.     slipUnit->su_Unit.unit_OpenCnt--;
  187.     if(!slipUnit->su_Unit.unit_OpenCnt)
  188.     {
  189.         ExpungeUnit(slipUnit,slipDevice);
  190.     }
  191.  
  192.     slipDevice->sd_Device.lib_OpenCnt--;
  193.  
  194.     ReleaseSemaphore(&slipDevice->sd_Lock);
  195.  
  196.     /* Check to see if we've been asked to expunge. */
  197.     if(slipDevice->sd_Device.lib_Flags & LIBF_DELEXP)
  198.         seglist = DevExpunge(slipDevice);
  199.  
  200.     return(seglist);
  201. }
  202.  
  203.  
  204. /*
  205. ** Device Expunge vector
  206. **
  207. ** a6 - Device base
  208. **
  209. ** Note: You may NEVER EVER Wait() in expunge. Period.
  210. **       Don't even *think* about it.
  211. */
  212.  
  213. BPTR ASM DevExpunge(REG(a6) struct SLIPDevice *slipDevice)
  214. {
  215.     BPTR seglist;
  216.     ULONG devbase;
  217.     LONG devbasesize;
  218.  
  219.     if(slipDevice->sd_Device.lib_OpenCnt)
  220.     {
  221.         /* Sorry, we're busy.  We'll expunge later on
  222.            if we can. */
  223.         slipDevice->sd_Device.lib_Flags |= LIBF_DELEXP;
  224.         seglist = (BPTR)0L;
  225.     }
  226.     else
  227.     {
  228.         /* Free up our library base and function table after
  229.            removing ourselves from the library list. */
  230.         Remove((struct Node *)slipDevice);
  231.         seglist = slipDevice->sd_SegList;
  232.  
  233.         devbase = (ULONG) slipDevice;
  234.  
  235.         devbasesize = (ULONG)slipDevice->sd_Device.lib_NegSize;
  236.         devbase = devbase - devbasesize;
  237.  
  238.         devbasesize += (ULONG)slipDevice->sd_Device.lib_PosSize;
  239.  
  240.         FreeMem((APTR)devbase,devbasesize);
  241.     }
  242.     return(seglist);
  243. }
  244.  
  245. /*
  246. ** InitSLIPUnit
  247. **
  248. ** Initialize (if needed) a new SLIP device Unit and process.
  249. **
  250. */
  251.  
  252. struct SLIPUnit *InitSLIPUnit(ULONG s2unit,
  253.                               struct SLIPDevice *slipDevice)
  254. {
  255.     struct SLIPUnit *slipUnit;
  256.     struct TagItem NPTags[]={NP_Entry, 0, NP_Name, 0, NP_Priority, SLIP_PRI , TAG_DONE, 0};
  257.     struct MsgPort *replyport;
  258.  
  259.     /* Check to see if the Unit is already up and running.  If
  260.        it is, just drop through.  If not, try to start it up. */
  261.  
  262.     if(!slipDevice->sd_Units[s2unit])
  263.     {
  264.         /* Open up dos.library */
  265.         if(slipDevice->sd_DOSBase = OpenLibrary("dos.library",37L))
  266.         {
  267.             /* Allocate a new Unit structure */
  268.             if(slipUnit = AllocMem(sizeof(struct SLIPUnit), MEMF_CLEAR|MEMF_PUBLIC))
  269.             {
  270.                 /* Do some initialization on the Unit structure */
  271.  
  272.                 NewList(&slipUnit->su_Unit.unit_MsgPort.mp_MsgList);
  273.  
  274.                 slipUnit->su_Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
  275.                 slipUnit->su_Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
  276.                 slipUnit->su_Unit.unit_MsgPort.mp_Node.ln_Name = "slip.device";
  277.  
  278.                 slipUnit->su_UnitNum = s2unit;
  279.                 slipUnit->su_Device     = (struct Device *) slipDevice;
  280.  
  281.                 NewList((struct List *)&slipUnit->su_Events);
  282.                 NewList((struct List *)&slipUnit->su_BuffMgmt);
  283.                 NewList((struct List *)&slipUnit->su_Track);
  284.  
  285. #ifdef OWNDEVUNIT_SUPPORT
  286.         sprintf(slipUnit->su_OwnerName, "slip.device unit %ld", s2unit);
  287. #endif
  288.                 /* Try to read in our configuration file */
  289.                 if(ReadConfig(slipUnit,slipDevice))
  290.                 {
  291.                     /* Start up the unit process */
  292.                     if(replyport = CreateMsgPort())
  293.                     {
  294.                         slipDevice->sd_Startup.Msg.mn_ReplyPort = replyport;
  295.                         slipDevice->sd_Startup.Device = (struct Device *) slipDevice;
  296.                         slipDevice->sd_Startup.Unit = (struct Unit *)slipUnit;
  297.  
  298.                         NPTags[0].ti_Data = (ULONG) &DevProcEntry;       /* Assembly entry point for the unit process. */
  299.  
  300.                         /* Maybe this should be different for each unit? */
  301.                         NPTags[1].ti_Data = (ULONG) "slip.device";      /* Process name */
  302.  
  303.                         ExtDeviceBase = (struct Library *)slipDevice;
  304.  
  305.                         if(slipUnit->su_Proc = CreateNewProc(NPTags))
  306.                         {
  307.                             PutMsg(&slipUnit->su_Proc->pr_MsgPort,(struct Message *)&slipDevice->sd_Startup);
  308.                             WaitPort(replyport);
  309.                             GetMsg(replyport);
  310.                         }
  311.                         DeleteMsgPort(replyport);
  312.                     }
  313.                 }
  314.                 if(!slipUnit->su_Proc)
  315.                 {
  316.                     /* The Unit process couldn't start for some reason, so free the Unit structure. */
  317.                     FreeMem(slipUnit,sizeof(struct SLIPUnit));
  318.                 }
  319.                 else
  320.                 {
  321.                     /* Set up the Unit structure pointer in the device base */
  322.                     slipDevice->sd_Units[s2unit] = (struct Unit *)slipUnit;
  323.                 }
  324.             }
  325.             CloseLibrary(slipDevice->sd_DOSBase);
  326.         }
  327.     }
  328.     return((struct SLIPUnit *)slipDevice->sd_Units[s2unit]);
  329. }
  330.  
  331. /*
  332. **
  333. ** ExpungeUnit
  334. **
  335. ** Tells a unit process to go away...
  336. **
  337. ** This function is called from the DevClose routine when the open count for a
  338. ** unit reaches zero.  This routine signals the unit process to exit and then
  339. ** waits for the unit process to acknowledge.  The unit structure is then
  340. ** freed.
  341. */
  342.  
  343. VOID ExpungeUnit(struct SLIPUnit *slipUnit,
  344.                  struct SLIPDevice *slipDevice)
  345. {
  346.     struct Task *unittask;
  347.  
  348.     unittask = (struct Task *)slipUnit->su_Proc;
  349.  
  350.     slipUnit->su_Proc = (struct Process *)FindTask(0L);
  351.  
  352.     Signal(unittask,SIGBREAKF_CTRL_F);
  353.     Wait(SIGBREAKF_CTRL_F);
  354.  
  355.     slipDevice->sd_Units[slipUnit->su_UnitNum] = NULL;
  356.  
  357.     FreeMem(slipUnit, sizeof(struct SLIPUnit));
  358. }
  359.  
  360. /*
  361. **
  362. ** ReadConfig
  363. **
  364. ** Attempt to read in and parse the driver's configuration file.
  365. **
  366. ** The files are named by ENV:SANA2/slipX.config where X is the decimal
  367. ** representation of the device's unit number.
  368. **
  369. */
  370.  
  371. BOOL ReadConfig(struct SLIPUnit *slipUnit,
  372.                 struct SLIPDevice *slipDevice)
  373. {
  374.     UBYTE *linebuff,buff[40];
  375.     STRPTR termchar;
  376.     struct RDArgs *rdargs;
  377.     BPTR ConfigFile;
  378.     LONG args[11];
  379.  
  380.     BOOL status = FALSE;
  381.     ULONG linenum=0;
  382.  
  383.     /* Create the name of our config file.. */
  384.     sprintf(buff,"ENV:SANA2/slip%ld.config",(ULONG)slipUnit->su_UnitNum);
  385.  
  386.     /* ...and open it. */
  387.     if(ConfigFile = Open(buff,MODE_OLDFILE))
  388.     {
  389.         /* Here, I use ReadArgs() to do the file parsing for me. */
  390.  
  391.         if(linebuff = AllocMem(256,MEMF_CLEAR|MEMF_PUBLIC))
  392.         {
  393.             if(rdargs = AllocDosObject(DOS_RDARGS, NULL))
  394.             {
  395.                 while(FGets(ConfigFile, linebuff, 255))
  396.                 {
  397.                     linenum++;
  398.                     if(linebuff[0] == '#') /* Skip comment lines */
  399.                         continue;
  400.  
  401.                     rdargs->RDA_Source.CS_Buffer = linebuff;
  402.                     rdargs->RDA_Source.CS_Length = 256;
  403.                     rdargs->RDA_Source.CS_CurChr = 0;
  404.  
  405.                     /* ReadArgs() requires that the line be null-terminated
  406.                        or funny things happen. */
  407.  
  408.                     termchar = (STRPTR) linebuff + strlen(linebuff);
  409.                     *termchar = '\n';
  410.                     termchar++;
  411.                     *termchar = 0;
  412.  
  413.                     memset ((char *) args, 0, sizeof(args));
  414.  
  415.                     /* Parse the line...*/
  416.  
  417.                     if(ReadArgs("SERNAME/A,SERUNIT/A/N,SERBAUD/A/N,IPSTR/A,CD=CARRIERDETECT/S,7WIRE/S,COMP/S,AUTO/S,MTU/K/N,SERBUF/K/N,USEODU/S",args,rdargs))
  418.                     {
  419.                         strcpy(slipUnit->su_SerDevName,(STRPTR)args[0]);
  420.                         slipUnit->su_SerUnitNum = *((ULONG *)args[1]);
  421.                         slipUnit->su_BaudRate = *((ULONG *)args[2]);
  422.             slipUnit->su_StAddr = 0;
  423.                         slipUnit->su_DefaultAddr  = IPToNum((STRPTR)args[3]);
  424.  
  425.                         if(args[4])
  426.                             slipUnit->su_State |= SLIPUF_CD;
  427.                         if(args[5])
  428.                             slipUnit->su_State |= SLIPUF_7WIRE;
  429.                         if(args[6])
  430.                             slipUnit->su_State |= SLIPUF_MAYCOMPRESS;
  431.                         if(args[7])
  432.                             slipUnit->su_State |= SLIPUF_AUTOCOMP;
  433.                         if(args[8])
  434.                             slipUnit->su_MTU = *((ULONG *)args[8]);
  435.                          else
  436.                             slipUnit->su_MTU = DEFAULT_SLIP_MTU;
  437.                         if(args[9])
  438.                             slipUnit->su_RBufLen = *((ULONG *)args[9]);
  439.                         else
  440.                             slipUnit->su_RBufLen = 16384L;
  441. #ifdef OWNDEVUNIT_SUPPORT
  442.             if (args[10])
  443.                 slipUnit->su_ODUBase = OpenLibrary(ODU_NAME, 0L);
  444.              else
  445.                 slipUnit->su_ODUBase = (struct Library *)NULL;
  446. #endif
  447.                         status = TRUE;
  448.                         FreeArgs(rdargs);
  449.                         break;
  450.                     }
  451.                     else
  452.                     {
  453.                         struct Library *IntuitionBase;
  454.                         struct EasyStruct es;
  455.                         if(IntuitionBase = OpenLibrary("intuition.library",37L))
  456.                         {
  457.                             es.es_StructSize=sizeof(struct EasyStruct);
  458.                             es.es_Flags=0;
  459.                             es.es_Title="Slip.device";
  460.                             es.es_TextFormat="Error in configuration file on line %ld.";
  461.                             es.es_GadgetFormat="Okay";
  462.                             EasyRequestArgs(NULL, &es, 0, &linenum);
  463.                             CloseLibrary(IntuitionBase);
  464.                         }
  465.                         break;
  466.                     }
  467.  
  468.                 }
  469.                 FreeDosObject(DOS_RDARGS,rdargs);
  470.             }
  471.             FreeMem(linebuff, 256);
  472.         }
  473.         Close(ConfigFile);
  474.     }
  475.     return(status);
  476. }
  477.  
  478.  
  479. /*
  480. **
  481. ** BeginIO
  482. **
  483. ** This is the dispatch point for the driver's incoming IORequests.
  484. **
  485. ** Registers at entry:
  486. **
  487. ** a1 = IORequest
  488. ** a6 = Device Base
  489. **
  490. */
  491.  
  492. #define SLIP_IMMEDIATES 0L
  493.  
  494. VOID ASM DevBeginIO(REG(a1) struct IOSana2Req *ios2,
  495.                     REG(a6) struct SLIPDevice *slipDevice)
  496. {
  497.     ios2->ios2_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  498.  
  499.     if(ios2->ios2_Req.io_Command < S2_END)
  500.     {
  501.         if((1L << ios2->ios2_Req.io_Command) & SLIP_IMMEDIATES)
  502.         {
  503.             PerformIO(ios2,slipDevice);
  504.         }
  505.         else
  506.         {
  507.             ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
  508.             PutMsg((struct MsgPort *)ios2->ios2_Req.io_Unit,(struct Message *)ios2);
  509.         }
  510.     }
  511.     else
  512.     {
  513.         ios2->ios2_Req.io_Error = IOERR_NOCMD;
  514.         TermIO(ios2,slipDevice);
  515.     }
  516. }
  517.  
  518. /*
  519. ** This routine is used to dispatch an IO request either from BeginIO
  520. ** or from the Unit process.
  521. */
  522.  
  523. VOID PerformIO(struct IOSana2Req *ios2,
  524.                struct SLIPDevice *slipDevice)
  525. {
  526.     struct SLIPUnit *slipUnit;
  527.  
  528.     slipUnit    = (struct SLIPUnit *)ios2->ios2_Req.io_Unit;
  529.  
  530.     ios2->ios2_Req.io_Error = 0;
  531.  
  532.     switch(ios2->ios2_Req.io_Command)
  533.     {
  534.         case CMD_READ:              ReadPacket(ios2,slipUnit,slipDevice);
  535.                                     break;
  536.  
  537.         case CMD_WRITE:             WritePacket(ios2,slipUnit,slipDevice);
  538.                                     break;
  539.  
  540.         case S2_DEVICEQUERY:        DeviceQuery(ios2,slipUnit,slipDevice);
  541.                                     break;
  542.  
  543.         case S2_GETSTATIONADDRESS:  GetStationAddress(ios2,slipUnit,slipDevice);
  544.                                     break;
  545.  
  546.         case S2_CONFIGINTERFACE:    ConfigInterface(ios2,slipUnit,slipDevice);
  547.                                     break;
  548.  
  549.         /* These commands are not appropriate for SLIP/CSLIP */
  550.         case S2_READORPHAN:
  551.         case S2_ADDMULTICASTADDRESS:
  552.         case S2_DELMULTICASTADDRESS:
  553.         case S2_MULTICAST:          ios2->ios2_Req.io_Error = S2ERR_NOT_SUPPORTED;
  554.                                     ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  555.                                     TermIO(ios2,slipDevice);
  556.                                     break;
  557.  
  558.         case S2_BROADCAST:          WritePacket(ios2,slipUnit,slipDevice);
  559.                                     break;
  560.  
  561.         case S2_TRACKTYPE:          TrackType(ios2,slipUnit,slipDevice);
  562.                                     break;
  563.  
  564.         case S2_UNTRACKTYPE:        UnTrackType(ios2,slipUnit,slipDevice);
  565.                                     break;
  566.  
  567.         case S2_GETTYPESTATS:       GetTypeStats(ios2,slipUnit,slipDevice);
  568.                                     break;
  569.  
  570.         case S2_GETSPECIALSTATS:    GetSpecialStats(ios2,slipUnit,slipDevice);
  571.                                     break;
  572.  
  573.         case S2_GETGLOBALSTATS:     GetGlobalStats(ios2,slipUnit,slipDevice);
  574.                                     break;
  575.  
  576.         case S2_ONEVENT:            OnEvent(ios2,slipUnit,slipDevice);
  577.                                     break;
  578.  
  579.         case S2_ONLINE:             Online(ios2,slipUnit,slipDevice);
  580.                                     break;
  581.  
  582.         case S2_OFFLINE:            Offline(ios2,slipUnit,slipDevice);
  583.                                     break;
  584.  
  585.         default:                    ios2->ios2_Req.io_Error = IOERR_NOCMD;
  586.                                     TermIO(ios2,slipDevice);
  587.                                     break;
  588.     }
  589. }
  590.  
  591. /*
  592. ** This function returns any device specific statistics that
  593. ** we may have.  Unfortunately, we don't have and SLIP specific
  594. ** statistics.
  595. */
  596. VOID ASM GetSpecialStats(STDSLIPARGS)
  597. {
  598.     struct Sana2SpecialStatHeader *stats;
  599.  
  600.     stats = (struct Sana2SpecialStatHeader *)ios2->ios2_StatData;
  601.  
  602.     stats->RecordCountSupplied = 0;
  603.     TermIO(ios2,slipDevice);
  604. }
  605.  
  606. /*
  607. ** This function returns the global statistics for the
  608. ** slip device.
  609. */
  610. VOID ASM GetGlobalStats(STDSLIPARGS)
  611. {
  612.     struct Sana2DeviceStats *stats;
  613.  
  614.     stats = (struct Sana2DeviceStats *)ios2->ios2_StatData;
  615.  
  616.     stats->PacketsReceived      = slipUnit->su_Stats.PacketsReceived;
  617.     stats->PacketsSent          = slipUnit->su_Stats.PacketsSent;
  618.     stats->BadData              = slipUnit->su_Stats.BadData;
  619.     stats->Overruns             = slipUnit->su_Stats.Overruns;
  620.     stats->UnknownTypesReceived = slipUnit->su_Stats.UnknownTypesReceived;
  621.     stats->Reconfigurations     = slipUnit->su_Stats.Reconfigurations;
  622.     stats->LastStart.tv_secs    = slipUnit->su_Stats.LastStart.tv_secs;
  623.     stats->LastStart.tv_micro   = slipUnit->su_Stats.LastStart.tv_micro;
  624.  
  625.     ios2->ios2_Req.io_Error = 0;
  626.  
  627.     TermIO(ios2,slipDevice);
  628. }
  629.  
  630. /*
  631. ** This function returns statistics for a specific
  632. ** type of packet that is being tracked.  Unfortunately,
  633. ** SLIP can't differentiate between different packet
  634. ** types, which makes packet type tracking essentially
  635. ** useless as the numbers would essentially be the same
  636. ** as those found via S2_GETGLOBALSTATS.
  637. **
  638. ** Just to be thourough, I have arbitrarily picked
  639. ** the packet type for SLIP IP packets to be 2048, the
  640. ** same as tha used for Ethernet.  This will at least
  641. ** allow you to track IP packets.
  642. */
  643. VOID ASM GetTypeStats(STDSLIPARGS)
  644. {
  645.     struct Sana2PacketTypeStats *stats;
  646.     struct SuperS2PTStats *sstats;
  647.  
  648.     ObtainSemaphore(&slipUnit->su_ListLock);
  649.  
  650.     stats = (struct Sana2PacketTypeStats *)ios2->ios2_StatData;
  651.     sstats = (struct SuperS2PTStats *)slipUnit->su_Track.mlh_Head;
  652.  
  653.     while(sstats->ss_Node.mln_Succ)
  654.     {
  655.         if(ios2->ios2_PacketType == sstats->ss_PType)
  656.         {
  657.             stats->PacketsSent = sstats->ss_Stats.PacketsSent;
  658.             stats->PacketsReceived = sstats->ss_Stats.PacketsReceived;
  659.             stats->BytesSent = sstats->ss_Stats.BytesSent;
  660.             stats->BytesReceived = sstats->ss_Stats.BytesReceived;
  661.             stats->PacketsDropped = sstats->ss_Stats.PacketsDropped;
  662.             break;
  663.         }
  664.         sstats = (struct SuperS2PTStats *)sstats->ss_Node.mln_Succ;
  665.     }
  666.     ReleaseSemaphore(&slipUnit->su_ListLock);
  667.     if(!sstats->ss_Node.mln_Succ)
  668.     {
  669.         ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  670.         ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  671.     }
  672.     TermIO(ios2,slipDevice);
  673. }
  674.  
  675. /*
  676. ** This function adds a packet type to the list
  677. ** of those that are being tracked.
  678. */
  679. VOID ASM TrackType(STDSLIPARGS)
  680. {
  681.     struct SuperS2PTStats *stats;
  682.  
  683.     ObtainSemaphore(&slipUnit->su_ListLock);
  684.  
  685.     stats = (struct SuperS2PTStats *)slipUnit->su_Track.mlh_Head;
  686.  
  687.     while(stats->ss_Node.mln_Succ)
  688.     {
  689.         if(ios2->ios2_PacketType == stats->ss_PType)
  690.         {
  691.             ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  692.             ios2->ios2_WireError = S2WERR_ALREADY_TRACKED;
  693.             break;
  694.         }
  695.         stats = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
  696.     }
  697.     if(!stats->ss_Node.mln_Succ)
  698.     {
  699.         if(stats = AllocMem(sizeof(struct SuperS2PTStats),MEMF_CLEAR|MEMF_PUBLIC))
  700.         {
  701.             stats->ss_PType = ios2->ios2_PacketType;
  702.             if(ios2->ios2_PacketType == 2048)
  703.                 slipUnit->su_IPTrack = stats;
  704.             AddTail((struct List *)&slipUnit->su_Track,(struct Node     *)stats);
  705.         }
  706.     }
  707.     ReleaseSemaphore(&slipUnit->su_ListLock);
  708.  
  709.     TermIO(ios2,slipDevice);
  710. }
  711.  
  712. /*
  713. ** This function removes a packet type from the
  714. ** list of those that are being tracked.
  715. */
  716. VOID ASM UnTrackType(STDSLIPARGS)
  717. {
  718.     struct SuperS2PTStats *stats;
  719.     struct SuperS2PTStats *stats_next;
  720.  
  721.     ObtainSemaphore(&slipUnit->su_ListLock);
  722.  
  723.     stats = (struct SuperS2PTStats *)slipUnit->su_Track.mlh_Head;
  724.  
  725.     while(stats->ss_Node.mln_Succ)
  726.     {
  727.         stats_next = (struct SuperS2PTStats *)stats->ss_Node.mln_Succ;
  728.         if(ios2->ios2_PacketType == stats->ss_PType)
  729.         {
  730.             if(ios2->ios2_PacketType == 2048)
  731.                 slipUnit->su_IPTrack = NULL;
  732.             Remove((struct Node *)stats);
  733.             FreeMem(stats,sizeof(struct SuperS2PTStats));
  734.             stats = NULL;
  735.             break;
  736.         }
  737.         stats = stats_next;
  738.     }
  739.     if(stats)
  740.     {
  741.         ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  742.         ios2->ios2_WireError = S2WERR_NOT_TRACKED;
  743.     }
  744.     ReleaseSemaphore(&slipUnit->su_ListLock);
  745.  
  746.     TermIO(ios2,slipDevice);
  747. }
  748.  
  749. /*
  750. ** This function is called whenever we receive a packet
  751. ** from the serial device driver.
  752. **
  753. */
  754. VOID PacketReceived(ULONG length,
  755.             struct SLIPUnit *slipUnit)
  756. {
  757.     slipUnit->su_Stats.PacketsReceived++;
  758.  
  759.     if(slipUnit->su_IPTrack)
  760.     {
  761.         slipUnit->su_IPTrack->ss_Stats.PacketsReceived++;
  762.         slipUnit->su_IPTrack->ss_Stats.BytesReceived+=length;
  763.     }
  764. }
  765.  
  766. /*
  767. ** This function is called whenever a packet is
  768. ** sent to the serial device driver.
  769. */
  770. VOID PacketSent(ULONG length,
  771.         struct SLIPUnit *slipUnit)
  772. {
  773.     slipUnit->su_Stats.PacketsSent++;
  774.  
  775.     if(slipUnit->su_IPTrack)
  776.     {
  777.         slipUnit->su_IPTrack->ss_Stats.PacketsSent++;
  778.         slipUnit->su_IPTrack->ss_Stats.BytesSent+=length;
  779.     }
  780. }
  781.  
  782. /*
  783. ** This function is called whenever a packet that
  784. ** is too large is received.
  785. */
  786. VOID PacketOverrun(struct SLIPUnit *slipUnit,
  787.                    struct SLIPDevice *slipDevice)
  788. {
  789.     slipUnit->su_Stats.Overruns++;
  790.     DoEvent(S2EVENT_ERROR|S2EVENT_RX,slipUnit,slipDevice);
  791. }
  792.  
  793. /*
  794. ** This function is called whenever a packet with
  795. ** garbage data is encountered.
  796. */
  797. VOID ReceivedGarbage(struct SLIPUnit *slipUnit,
  798.                      struct SLIPDevice *slipDevice)
  799. {
  800.     slipUnit->su_Stats.BadData++;
  801.     DoEvent(S2EVENT_ERROR|S2EVENT_RX,slipUnit,slipDevice);
  802. }
  803.  
  804. /*
  805. ** This function is called whenever a packet
  806. ** is dropped by the SLIP driver.
  807. */
  808. VOID PacketDropped(struct SLIPUnit *slipUnit,
  809.            struct SLIPDevice *slipDevice)
  810. {
  811.     if(slipUnit->su_IPTrack)
  812.     {
  813.         slipUnit->su_IPTrack->ss_Stats.PacketsDropped++;
  814.     }
  815.     DoEvent(S2EVENT_ERROR|S2EVENT_RX,slipUnit,slipDevice);
  816. }
  817.  
  818. /*
  819. ** This function is used to return an IO request
  820. ** back to the sender.
  821. */
  822. VOID ASM TermIO(REG(a2) struct IOSana2Req *ios2,
  823.             REG(a6) struct SLIPDevice *slipDevice)
  824. {
  825.     if(!(ios2->ios2_Req.io_Flags & IOF_QUICK))
  826.         ReplyMsg((struct Message *)ios2);
  827. }
  828.  
  829. /*
  830. ** The device AbortIO() entry point.
  831. **
  832. ** A1 - The IO request to be aborted.
  833. ** A6 - The device base.
  834. */
  835. ULONG ASM DevAbortIO(REG(a1) struct IOSana2Req *ios2,
  836.                      REG(a6) struct SLIPDevice *slipDevice)
  837. {
  838.     ULONG result = 0L;
  839.     struct SLIPUnit *slipUnit;
  840.     struct BufferManagement *bm;
  841.  
  842.     slipUnit = (struct SLIPUnit *)ios2->ios2_Req.io_Unit;
  843.     ObtainSemaphore(&slipUnit->su_ListLock);
  844.     if(ios2->ios2_Req.io_Message.mn_Node.ln_Type != NT_REPLYMSG)
  845.     {
  846.         switch(ios2->ios2_Req.io_Command)
  847.         {
  848.                 /* Walk the list of BufferManagement structs, trying AbortReq()
  849.                    on each. */
  850.  
  851.                 case CMD_READ:  bm = (struct BufferManagement *)slipUnit->su_BuffMgmt.mlh_Head;
  852.                                 while(bm->bm_Node.mln_Succ)
  853.                                 {
  854.                                     /* If result is 0, the IORequest was found,
  855.                                        so we're done. */
  856.                                     if(!(result=AbortReq(&bm->bm_RxQueue,ios2,slipDevice)))
  857.                                         break;
  858.  
  859.                                     bm = (struct BufferManagement *)bm->bm_Node.mln_Succ;
  860.                                 }
  861.                                 break;
  862.  
  863.                 case CMD_WRITE: Disable();
  864.                                 if(!(result=AbortReq((struct MinList *)&slipUnit->su_Tx->mp_MsgList,ios2,slipDevice)))
  865.                                     result=AbortReq((struct MinList *)&slipUnit->su_TxFast->mp_MsgList,ios2,slipDevice);
  866.                                 Enable();
  867.                                 break;
  868.  
  869.                 case S2_ONEVENT:        result=AbortReq(&slipUnit->su_Events,ios2,slipDevice);
  870.                                         break;
  871.  
  872.                 default:                result=IOERR_NOCMD;
  873.                                         break;
  874.         }
  875.     }
  876.     ReleaseSemaphore(&slipUnit->su_ListLock);
  877.     return(result);
  878. }
  879.  
  880. /*
  881. ** This funcion is used to locate an IO request in a linked
  882. ** list and abort it if found.
  883. */
  884. ULONG AbortReq(struct MinList *minlist,
  885.                struct IOSana2Req *ios2,
  886.                struct SLIPDevice *slipDevice)
  887. {
  888.     struct Node *node, *next;
  889.     ULONG result=IOERR_NOCMD;
  890.  
  891.     node = (struct Node *)minlist->mlh_Head;
  892.  
  893.     while(node->ln_Succ)
  894.     {
  895.         next = node->ln_Succ;
  896.  
  897.         if(node == (struct Node *)ios2)
  898.         {
  899.             Remove((struct Node *)ios2);
  900.             ios2->ios2_Req.io_Error = IOERR_ABORTED;
  901.             TermIO(ios2,slipDevice);
  902.             result = 0;
  903.             break;
  904.         }
  905.         node = next;
  906.     }
  907.     return(result);
  908. }
  909.  
  910. /*
  911. ** This function handles S2_CONFIGINTERFACE commands.
  912. */
  913. VOID ASM ConfigInterface(STDSLIPARGS)
  914. {
  915.     /* Note: we may only be configured once. */
  916.     if(!(slipUnit->su_State & SLIPUF_CONFIG))
  917.     {
  918.         if(OpenSerial(slipUnit,slipDevice))
  919.         {
  920.             /* FIXED - Now sets our address to whatever the
  921.                protocol stack says to use. */
  922.             CopyMem(&ios2->ios2_SrcAddr,&slipUnit->su_StAddr,4);
  923.             slipUnit->su_State |= SLIPUF_CONFIG;
  924.         }
  925.     }
  926.     else
  927.     {
  928.         /* Sorry, we're already configured. */
  929.         ios2->ios2_Req.io_Error = S2ERR_BAD_STATE;
  930.         ios2->ios2_WireError = S2WERR_IS_CONFIGURED;
  931.     }
  932.     TermIO(ios2,slipDevice);
  933. }
  934.  
  935. /*
  936. ** This function handles S2_GETSTATIONADDRESS commands.
  937. **
  938. ** We don't really have a hardware address, so we will
  939. ** just clear the source address field.
  940. */
  941.  
  942. VOID ASM GetStationAddress(STDSLIPARGS)
  943. {
  944.     UBYTE i;
  945.  
  946.     for(i=0; i< SANA2_MAX_ADDR_BYTES; i++)
  947.     {
  948.         ios2->ios2_SrcAddr[i]=0;
  949.         ios2->ios2_DstAddr[i]=0;
  950.     }
  951.     CopyMem(&slipUnit->su_StAddr,&ios2->ios2_SrcAddr,4);
  952.     CopyMem(&slipUnit->su_DefaultAddr,&ios2->ios2_DstAddr,4);
  953.  
  954.     TermIO(ios2,slipDevice);
  955. }
  956.  
  957. /*
  958. ** Init Table for the Sana2DeviceQuery structure.
  959. */
  960.  
  961. struct DQInfo DQTable[9] =
  962. {
  963.         DQ_CLONG,       4,      0,      /* This and the next are placeholders. */
  964.         DQ_CLONG,       4,      0,
  965.         DQ_CLONG,       4,      0,
  966.         DQ_CLONG,       4,      0,
  967.         DQ_CWORD,       2,      32,
  968.         DQ_MTU,         4,      0,
  969.         DQ_BPS,         4,      0,
  970.         DQ_CLONG,       4,      S2WireType_SLIP,
  971.         0,              0,      0
  972. };
  973.  
  974. /*
  975. ** This function handles S2_DEVICEQUERY comands.
  976. */
  977. VOID ASM DeviceQuery(STDSLIPARGS)
  978. {
  979.     ULONG size, supplied;
  980.     UWORD i;
  981.     UBYTE *w_byte;
  982.     struct DQInfo *dqi;
  983.  
  984.     struct Sana2DeviceQuery *sdq;
  985.  
  986.     sdq = (struct Sana2DeviceQuery *)ios2->ios2_StatData;
  987.     size = sdq->SizeAvailable;
  988.     supplied = 0;
  989.     dqi = &DQTable[0];
  990.  
  991.     for(i = 0,w_byte = (UBYTE *)ios2->ios2_StatData; (dqi->Size && (dqi->Size <= size)); i++)
  992.     {
  993.         size -= dqi->Size;
  994.         supplied += dqi->Size;
  995.         dqi = &DQTable[i];
  996.  
  997.         switch(dqi->Type)
  998.         {
  999.                 /* Ant of these are constants */
  1000.  
  1001.                 case DQ_CWORD : *(UWORD *)w_byte = dqi->Data;
  1002.                                 w_byte = (UBYTE *)((ULONG)w_byte + 2);
  1003.                                 break;
  1004.  
  1005.                 case DQ_CLONG : *(ULONG *)w_byte = dqi->Data;
  1006.                                 w_byte = (UBYTE *)((ULONG)w_byte + 4);
  1007.                                 break;
  1008.  
  1009.                 /* These two are configuration dependant. */
  1010.  
  1011.                 case DQ_MTU  :  *(ULONG *)w_byte = slipUnit->su_MTU;
  1012.                                 w_byte = (UBYTE *)((ULONG)w_byte + 4);
  1013.                                 break;
  1014.  
  1015.                 case DQ_BPS  :  *(ULONG *)w_byte = slipUnit->su_BaudRate;
  1016.                                 w_byte = (UBYTE *)((ULONG)w_byte + 4);
  1017.                                 break;
  1018.  
  1019.         }
  1020.     }
  1021.  
  1022.     /* I shouldn't have to check this, but I do it anyway for a sanity check. */
  1023.     if(sdq->SizeAvailable >= 8)
  1024.     {
  1025.         sdq->SizeSupplied = supplied;
  1026.     }
  1027.     TermIO(ios2,slipDevice);
  1028. }
  1029.  
  1030. /*
  1031. ** This function is used for handling CMD_WRITE
  1032. ** commands.
  1033. */
  1034. VOID ASM WritePacket(STDSLIPARGS)
  1035. {
  1036.     /* Make sure that we are online. */
  1037.     if(slipUnit->su_State & SLIPUF_ONLINE)
  1038.     {
  1039.         /* Make sure it's a legal length. */
  1040.         if(ios2->ios2_DataLength <= slipUnit->su_MTU)
  1041.         {
  1042.             /* Queue the request for the slip.device process. */
  1043.  
  1044.             ios2->ios2_Req.io_Flags &= ~IOF_QUICK;
  1045.  
  1046.             PutMsg(slipUnit->su_Tx,(struct Message *)ios2);
  1047.  
  1048.         }
  1049.         else
  1050.         {
  1051.             /* Sorry, the packet is too long! */
  1052.             ios2->ios2_Req.io_Error = S2ERR_MTU_EXCEEDED;
  1053.             ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  1054.             TermIO(ios2,slipDevice);
  1055.             DoEvent(S2EVENT_TX,slipUnit,slipDevice);
  1056.         }
  1057.     }
  1058.     else
  1059.     {
  1060.         /* Sorry, we're offline */
  1061.         ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1062.         ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1063.         TermIO(ios2,slipDevice);
  1064.     }
  1065. }
  1066.  
  1067. VOID ASM SendPacket(STDSLIPARGS)
  1068. {
  1069.     struct IOExtSer *ioser;
  1070.     struct BufferManagement *bm;
  1071.     ULONG framelength;
  1072.     UBYTE *hdr;
  1073.     u_char ptype;
  1074.  
  1075.     bm =(struct BufferManagement *) ios2->ios2_BufferManagement;
  1076.  
  1077.     /* Copy the data out of the packet into our temporary buffer. */
  1078.     if((*bm->bm_CopyFromBuffer)(slipUnit->su_TxBuff,ios2->ios2_Data,ios2->ios2_DataLength))
  1079.     {
  1080.         PacketSent(ios2->ios2_DataLength,slipUnit);
  1081.  
  1082.         /* See if this packet is TCP and we are allowed to compress packets. */
  1083.  
  1084.         if((((struct ip *)slipUnit->su_TxBuff)->ip_p == IPPROTO_TCP) &&
  1085.            (slipUnit->su_State & SLIPUF_MAYCOMPRESS))
  1086.         {
  1087.             slipUnit->su_MBuff.m_off = slipUnit->su_TxBuff;
  1088.             slipUnit->su_MBuff.m_len = ios2->ios2_DataLength;
  1089.             ptype = sl_compress_tcp(&slipUnit->su_MBuff,(struct ip *)slipUnit->su_TxBuff,&slipUnit->su_SLCompress, 1);
  1090.             if(ptype == 0x40)
  1091.             {
  1092.                 framelength=EncodeSLIP(slipUnit->su_TxBuff,slipUnit->su_TxSLIP,ios2->ios2_DataLength);
  1093.             }
  1094.             else
  1095.             {
  1096.                 hdr = slipUnit->su_MBuff.m_off;
  1097.                 hdr[0] |= ptype;
  1098.                 framelength=EncodeSLIP(slipUnit->su_MBuff.m_off,slipUnit->su_TxSLIP,slipUnit->su_MBuff.m_len);
  1099.             }
  1100.         }
  1101.  
  1102.         /* Either the packet isn't TCP or we're not allowed to use compression */
  1103.         else
  1104.         {
  1105.             /* Encode the packet in SLIP format */
  1106.             framelength=EncodeSLIP(slipUnit->su_TxBuff,slipUnit->su_TxSLIP,ios2->ios2_DataLength);
  1107.         }
  1108.         ioser = slipUnit->su_SerTx;
  1109.         ioser->IOSer.io_Data = slipUnit->su_TxSLIP;
  1110.         ioser->IOSer.io_Length = framelength;
  1111.         ioser->IOSer.io_Command = CMD_WRITE;
  1112.         ioser->IOSer.io_Error = 0;
  1113.         ioser->IOSer.io_Message.mn_Node.ln_Type = 0;
  1114.  
  1115.         /* Send the packet to the serial device driver */
  1116.         SendIO((struct IORequest *)ioser);
  1117.     }
  1118.     else
  1119.     {
  1120.         /* Something went wrong...*/
  1121.         ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1122.         ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  1123.         DoEvent(S2EVENT_BUFF,slipUnit,slipDevice);
  1124.     }
  1125.     TermIO(ios2,slipDevice);
  1126. }
  1127.  
  1128. /*
  1129. ** This routine encodes a packet in SLIP format.
  1130. **
  1131. ** The format is quite simple.
  1132. **
  1133. ** SLIP Encoding:
  1134. **
  1135. ** SLIP_ESC -> SLIP_ESC SLIP_ESC_ESC
  1136. ** SLIP_END -> SLIP_ESC SLIP_ESC_END
  1137. **
  1138. ** The packet is preceded and terminated with a SLIP_END as prescribed by
  1139. ** rfc 1055.
  1140. **
  1141. */
  1142. ULONG EncodeSLIP(UBYTE *source, UBYTE *dest, ULONG length)
  1143. {
  1144.     UBYTE ch;
  1145.     UBYTE *current;
  1146.  
  1147.     current = dest;
  1148.  
  1149.     *current = SLIP_END;
  1150.     current++;
  1151.  
  1152.     while(length--)
  1153.     {
  1154.         ch = *source;
  1155.         source++;
  1156.  
  1157.         if(ch == SLIP_ESC)
  1158.         {
  1159.             *current = SLIP_ESC;
  1160.             current++;
  1161.             ch = SLIP_ESC_ESC;
  1162.         }
  1163.         else if(ch == SLIP_END)
  1164.         {
  1165.             *current = SLIP_ESC;
  1166.             current ++;
  1167.             ch = SLIP_ESC_END;
  1168.         }
  1169.         *current = ch;
  1170.         current++;
  1171.     }
  1172.     *current = SLIP_END;
  1173.     current++;
  1174.  
  1175.     return((ULONG)(current - dest));
  1176. }
  1177.  
  1178. /*
  1179. ** This routine handles CMD_READ commands.  We
  1180. ** always queue these unless we're offline.
  1181. */
  1182. VOID ASM ReadPacket(STDSLIPARGS)
  1183. {
  1184.     struct BufferManagement *bm;
  1185.  
  1186.     if(slipUnit->su_State & SLIPUF_ONLINE)
  1187.     {
  1188.         /* Find the appropriate queue for this IO request */
  1189.  
  1190.         ObtainSemaphore(&slipUnit->su_ListLock);
  1191.         bm = (struct BufferManagement *)slipUnit->su_BuffMgmt.mlh_Head;
  1192.         while(bm->bm_Node.mln_Succ)
  1193.         {
  1194.             if(bm == (struct BufferManagement *)ios2->ios2_BufferManagement)
  1195.             {
  1196.                 AddTail((struct List *)&bm->bm_RxQueue,(struct Node *)ios2);
  1197.                 break;
  1198.             }
  1199.             bm = (struct BufferManagement *)bm->bm_Node.mln_Succ;
  1200.         }
  1201.         /* Did we fall of the end of the list? */
  1202.         if(!bm->bm_Node.mln_Succ)
  1203.         {
  1204.             ios2->ios2_Req.io_Error = S2ERR_BAD_ARGUMENT;
  1205.             ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  1206.             TermIO(ios2,slipDevice);
  1207.         }
  1208.         ReleaseSemaphore(&slipUnit->su_ListLock);
  1209.     }
  1210.     else
  1211.     {
  1212.         /* Sorry, we're offline */
  1213.         ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1214.         ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1215.         TermIO(ios2,slipDevice);
  1216.     }
  1217. }
  1218.  
  1219. /*
  1220. ** This routine initializes our IO requests and buffers
  1221. ** for serial i/o and SLIP encoding/decoding.
  1222. */
  1223. BOOL InitSerial(struct SLIPUnit *slipUnit,
  1224.                 struct SLIPDevice *slipDevice)
  1225. {
  1226.     ULONG *clr;
  1227.     BOOL status = FALSE;
  1228.  
  1229.     for(clr = (ULONG *) &slipUnit->su_SerRx; clr <= (ULONG *) &slipUnit->su_TxSLIP; clr++)
  1230.         *clr = 0L;
  1231.  
  1232.     if(slipUnit->su_TxPort = CreateMsgPort())
  1233.     {
  1234.         if(slipUnit->su_SerTx = CreateIORequest(slipUnit->su_TxPort,sizeof(struct IOExtSer)))
  1235.         {
  1236.             if(slipUnit->su_RxPort = CreateMsgPort())
  1237.             {
  1238.                 if(slipUnit->su_SerRx = CreateIORequest(slipUnit->su_RxPort,sizeof(struct IOExtSer)))
  1239.                 {
  1240.                     if(slipUnit->su_TxBuff = AllocMem((slipUnit->su_MTU + 128) * 2,MEMF_CLEAR|MEMF_PUBLIC))
  1241.                     {
  1242.                         slipUnit->su_RxBuff = slipUnit->su_TxBuff + slipUnit->su_MTU + 128;
  1243.                         slipUnit->su_RxBuffPtr = slipUnit->su_RxBuff + 128;
  1244.  
  1245.                         if(slipUnit->su_TxSLIP = AllocMem((slipUnit->su_MTU*2 + 128) * 2,MEMF_CLEAR|MEMF_PUBLIC))
  1246.                         {
  1247.                             slipUnit->su_RxSLIP = slipUnit->su_TxSLIP + slipUnit->su_MTU*2 + 128;
  1248.                             {
  1249.                                 status = TRUE;
  1250.                             }
  1251.                         }
  1252.                     }
  1253.                 }
  1254.             }
  1255.         }
  1256.     }
  1257.     if(!status)
  1258.         DeinitSerial(slipUnit,slipDevice);
  1259.     return(status);
  1260. }
  1261.  
  1262. /*
  1263. ** This routine cleans up our serial i/o requests
  1264. ** and misc. buffers.
  1265. */
  1266. VOID DeinitSerial(struct SLIPUnit *slipUnit,
  1267.                   struct SLIPDevice *slipDevice)
  1268. {
  1269.     if(slipUnit->su_SerTx)
  1270.         DeleteIORequest(slipUnit->su_SerTx);
  1271.  
  1272.     if(slipUnit->su_TxPort)
  1273.         DeleteMsgPort(slipUnit->su_TxPort);
  1274.  
  1275.     if(slipUnit->su_SerRx)
  1276.         DeleteIORequest(slipUnit->su_SerRx);
  1277.  
  1278.     if(slipUnit->su_RxPort)
  1279.         DeleteMsgPort(slipUnit->su_RxPort);
  1280.  
  1281.     if(slipUnit->su_TxBuff)
  1282.         FreeMem(slipUnit->su_TxBuff,(slipUnit->su_MTU + 128) * 2);
  1283.  
  1284.     if(slipUnit->su_TxSLIP)
  1285.         FreeMem(slipUnit->su_TxSLIP,(slipUnit->su_MTU*2 + 128) * 2);
  1286. }
  1287.  
  1288. /*
  1289. ** This routine handles S2_ONEVNET commands.
  1290. */
  1291. VOID ASM OnEvent(STDSLIPARGS)
  1292. {
  1293.  
  1294.     /* Two special cases. S2EVENT_ONLINE and S2EVENT_OFFLINE are supposed to
  1295.        retun immediately if we are already in the state that they are waiting
  1296.        for. */
  1297.  
  1298.     if( ((ios2->ios2_WireError & S2EVENT_ONLINE) && (slipUnit->su_State & SLIPUF_ONLINE)) ||
  1299.         ((ios2->ios2_WireError & S2EVENT_OFFLINE) && (!(slipUnit->su_State & SLIPUF_ONLINE))))
  1300.     {
  1301.         ios2->ios2_Req.io_Error = 0;
  1302.         ios2->ios2_WireError &= (S2EVENT_ONLINE|S2EVENT_OFFLINE);
  1303.         TermIO(ios2,slipDevice);
  1304.         return;
  1305.     }
  1306.  
  1307.     /* Queue anything else */
  1308.  
  1309.     ObtainSemaphore(&slipUnit->su_ListLock);
  1310.     AddTail((struct List *)&slipUnit->su_Events,(struct Node *)ios2);
  1311.     ReleaseSemaphore(&slipUnit->su_ListLock);
  1312. }
  1313.  
  1314. /*
  1315. ** This routine opens the serial device driver and attempts to bring
  1316. ** the device online.
  1317. */
  1318. BOOL OpenSerial(struct SLIPUnit *slipUnit,
  1319.                 struct SLIPDevice *slipDevice)
  1320. {
  1321.     BOOL status = TRUE;
  1322.     ULONG odflags = 0;
  1323. #ifdef OWNDEVUNIT_SUPPORT
  1324.     STRPTR oduError;
  1325. #endif
  1326.     slipUnit->su_SerRx->IOSer.io_Device = NULL;
  1327.  
  1328.     sl_compress_init(&slipUnit->su_SLCompress);
  1329.  
  1330. #ifdef OWNDEVUNIT_SUPPORT
  1331.     if(slipUnit->su_ODUBase)
  1332.     {
  1333.     oduError = AttemptDevUnit(slipUnit->su_SerDevName, slipUnit->su_SerUnitNum, slipUnit->su_OwnerName, 0L);
  1334.  
  1335.     if(oduError)
  1336.     {
  1337.             struct Library *IntuitionBase;
  1338.             struct EasyStruct es;
  1339.             ULONG args[3];
  1340.         STRPTR msg;
  1341.             args[0]=(ULONG)slipUnit->su_SerDevName;
  1342.             args[1]=(ULONG)slipUnit->su_SerUnitNum;
  1343.         args[2]=(ULONG)oduError;
  1344.         if (oduError[0] == ODUERR_LEADCHAR[0])
  1345.         {
  1346.             args[2]++;
  1347.             msg = "Error locking %s unit %ld: %s";
  1348.         }
  1349.         else
  1350.             msg = "%s unit %ld already owned by %s.";
  1351.  
  1352.             if(IntuitionBase = OpenLibrary("intuition.library",37L))
  1353.             {
  1354.                 es.es_StructSize=sizeof(struct EasyStruct);
  1355.                 es.es_Flags=0;
  1356.                 es.es_Title="Slip.device";
  1357.                 es.es_TextFormat=msg;
  1358.                 es.es_GadgetFormat="Okay";
  1359.                 EasyRequestArgs(NULL, &es, 0, (APTR)args);
  1360.                 CloseLibrary(IntuitionBase);
  1361.             }
  1362.  
  1363.         return FALSE;
  1364.     }
  1365.     }
  1366. #endif
  1367.     if(slipUnit->su_State &     SLIPUF_7WIRE)
  1368.         odflags = SERF_7WIRE;
  1369.  
  1370.     slipUnit->su_SerTx->io_SerFlags = odflags;
  1371.  
  1372.     if(!OpenDevice(slipUnit->su_SerDevName,slipUnit->su_SerUnitNum,(struct IORequest *)slipUnit->su_SerTx,odflags))
  1373.     {
  1374.         /* Set up our serial parameters */
  1375.         slipUnit->su_SerRx->IOSer.io_Device     = slipUnit->su_SerTx->IOSer.io_Device;
  1376.         slipUnit->su_SerRx->IOSer.io_Unit =     slipUnit->su_SerTx->IOSer.io_Unit;
  1377.  
  1378.         slipUnit->su_SerTx->IOSer.io_Command = SDCMD_SETPARAMS;
  1379.         slipUnit->su_SerTx->io_Baud     = slipUnit->su_BaudRate;
  1380.         slipUnit->su_SerTx->io_RBufLen = slipUnit->su_RBufLen;
  1381.         slipUnit->su_SerTx->io_ReadLen = 8;
  1382.         slipUnit->su_SerTx->io_WriteLen = 8;
  1383.         slipUnit->su_SerTx->io_StopBits = 1;
  1384.         slipUnit->su_SerTx->io_SerFlags = SERF_XDISABLED|SERF_RAD_BOOGIE;
  1385.  
  1386.         if(!DoIO((struct IORequest *)slipUnit->su_SerTx))
  1387.         {
  1388.             /* Assume we're now online */
  1389.             slipUnit->su_State |= SLIPUF_ONLINE;
  1390.  
  1391.             /* If we are running with auto-compression on, clear the
  1392.                current value of our COMPRESSION flag. */
  1393.  
  1394.             if(slipUnit->su_State &     SLIPUF_AUTOCOMP)
  1395.                 slipUnit->su_State &= ~SLIPUF_MAYCOMPRESS;
  1396.  
  1397.             /* Are we checking for serial detect? */
  1398.             if(slipUnit->su_State &     SLIPUF_CD)
  1399.             {
  1400.                 slipUnit->su_SerTx->IOSer.io_Command = SDCMD_QUERY;
  1401.                 if(!DoIO((struct IORequest *)slipUnit->su_SerTx))
  1402.                 {
  1403.                     if(slipUnit->su_SerTx->io_Status & (1<<5))
  1404.                     {
  1405.                         /* Sorry, no carrier, shut down the serial driver
  1406.                            and set our state to offline. */
  1407.                         CloseDevice((struct IORequest *)slipUnit->su_SerTx);
  1408. #ifdef OWNDEVUNIT_SUPPORT
  1409.             if (slipUnit->su_ODUBase)
  1410.                 FreeDevUnit(slipUnit->su_SerDevName, slipUnit->su_SerUnitNum);
  1411. #endif
  1412.                         slipUnit->su_State &= ~SLIPUF_ONLINE;
  1413.                     }
  1414.                 }
  1415.                 else
  1416.                     status = FALSE;
  1417.             }
  1418.             if(status)
  1419.             {
  1420.                 /* Queue up the initial CMD_READ command for the
  1421.                    serial driver. */
  1422.                 slipUnit->su_SerRx->IOSer.io_Command = CMD_READ;
  1423.                 slipUnit->su_SerRx->IOSer.io_Length     = 1;
  1424.                 slipUnit->su_SerRx->IOSer.io_Data =     slipUnit->su_RxSLIP;
  1425.                 SendIO((struct IORequest *)slipUnit->su_SerRx);
  1426.             }
  1427.         }
  1428.         else
  1429.             status = FALSE;
  1430.  
  1431.         if(!status)
  1432.             CloseDevice((struct IORequest *)slipUnit->su_SerTx);
  1433.     }
  1434.     else
  1435.     {
  1436.         struct Library *IntuitionBase;
  1437.         struct EasyStruct es;
  1438.         ULONG args[2];
  1439.         args[0]=(ULONG)slipUnit->su_SerDevName;
  1440.         args[1]=(ULONG)slipUnit->su_SerUnitNum;
  1441.         if(IntuitionBase = OpenLibrary("intuition.library",37L))
  1442.         {
  1443.             es.es_StructSize=sizeof(struct EasyStruct);
  1444.             es.es_Flags=0;
  1445.             es.es_Title="Slip.device";
  1446.             es.es_TextFormat="Couldn't open %s unit %ld.";
  1447.             es.es_GadgetFormat="Okay";
  1448.             EasyRequestArgs(NULL, &es, 0, (APTR)args);
  1449.             CloseLibrary(IntuitionBase);
  1450.         }
  1451.         status = FALSE;
  1452.     }
  1453.  
  1454.     if(slipUnit->su_State &     SLIPUF_ONLINE)
  1455.         MarkTimeOnline(slipUnit,slipDevice);
  1456.  
  1457. #ifdef OWNDEVUNIT_SUPPORT
  1458.     if(!status && slipUnit->su_ODUBase)
  1459.     FreeDevUnit(slipUnit->su_SerDevName, slipUnit->su_SerUnitNum);
  1460. #endif
  1461.  
  1462.     return(status);
  1463. }
  1464.  
  1465. /*
  1466. ** This routine gets the current system time and stores
  1467. ** it in our global statistics structure.
  1468. */
  1469.  
  1470. VOID MarkTimeOnline(struct SLIPUnit *slipUnit,
  1471.                     struct SLIPDevice *slipDevice)
  1472. {
  1473.     register struct Library *TimerBase;
  1474.     struct timerequest *treq;
  1475.  
  1476.     if(treq = (struct timerequest *)AllocMem(sizeof(struct timerequest),MEMF_PUBLIC|MEMF_CLEAR))
  1477.     {
  1478.         if(!OpenDevice("timer.device",UNIT_MICROHZ,(struct IORequest *)treq,0L))
  1479.         {
  1480.             TimerBase = (struct Library *)treq->tr_node.io_Device;
  1481.             GetSysTime(&slipUnit->su_Stats.LastStart);
  1482.             CloseDevice((struct IORequest *)treq);
  1483.         }
  1484.         FreeMem(treq,sizeof(struct timerequest));
  1485.     }
  1486. }
  1487.  
  1488. /*
  1489. ** This routine aborts any pending activity with the serial
  1490. ** device driver and then brings the slip driver offline.
  1491. */
  1492. VOID CloseSerial(struct SLIPUnit *slipUnit,
  1493.                  struct SLIPDevice *slipDevice)
  1494. {
  1495.     AbortIO((struct IORequest *)slipUnit->su_SerRx);
  1496.     WaitIO((struct IORequest *)slipUnit->su_SerRx);
  1497.  
  1498.     while(GetMsg(slipUnit->su_RxPort));
  1499.  
  1500.     AbortIO((struct IORequest *)slipUnit->su_SerTx);
  1501.     WaitIO((struct IORequest *)slipUnit->su_SerTx);
  1502.  
  1503.     while(GetMsg(slipUnit->su_TxPort));
  1504.  
  1505.     CloseDevice((struct IORequest *)slipUnit->su_SerRx);
  1506. #ifdef OWNDEVUNIT_SUPPORT
  1507.     if (slipUnit->su_ODUBase)
  1508.         FreeDevUnit(slipUnit->su_SerDevName, slipUnit->su_SerUnitNum);
  1509. #endif
  1510.     slipUnit->su_State &= ~SLIPUF_ONLINE;
  1511. }
  1512.  
  1513. /*
  1514. ** This routime handles CMD_ONLINE commands.
  1515. */
  1516. VOID ASM Online(STDSLIPARGS)
  1517. {
  1518.  
  1519.     if(!(slipUnit->su_State     & SLIPUF_ONLINE))
  1520.     {
  1521.         /* We're offline. Try to go online. */
  1522.         if(OpenSerial(slipUnit,slipDevice))
  1523.         {
  1524.             if(slipUnit->su_State &     SLIPUF_ONLINE)
  1525.             {
  1526.                 /* In case someone wants to know...*/
  1527.                 DoEvent(S2EVENT_ONLINE,slipUnit,slipDevice);
  1528.             }
  1529.             else
  1530.             {
  1531.                 /* Sorry, the attempt to go online failed. */
  1532.                 ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1533.                 ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1534.             }
  1535.         }
  1536.         else
  1537.         {
  1538.             /* A general problem occured. */
  1539.             ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1540.             ios2->ios2_WireError = S2WERR_GENERIC_ERROR;
  1541.         }
  1542.     }
  1543.     TermIO(ios2,slipDevice);
  1544. }
  1545.  
  1546. /*
  1547. ** This routine handles CMD_OFFLINE commands.
  1548. */
  1549. VOID ASM Offline(STDSLIPARGS)
  1550. {
  1551.     TermIO(ios2,slipDevice);
  1552.  
  1553.     if(slipUnit->su_State &     SLIPUF_ONLINE)
  1554.     {
  1555.         /* We're online, so shut everything down. */
  1556.         CloseSerial(slipUnit,slipDevice);
  1557.         DoOffline(slipUnit,slipDevice);
  1558.         DoEvent(S2EVENT_OFFLINE,slipUnit,slipDevice);
  1559.     }
  1560. }
  1561.  
  1562. /*
  1563. ** This routine is called whenever an "important"
  1564. ** SANA-II event occurs.
  1565. */
  1566. VOID DoEvent(ULONG events,
  1567.              struct SLIPUnit *slipUnit,
  1568.              struct SLIPDevice *slipDevice)
  1569. {
  1570.     struct IOSana2Req *ios2;
  1571.     struct IOSana2Req *ios2_next;
  1572.  
  1573.     ObtainSemaphore(&slipUnit->su_ListLock);
  1574.  
  1575.     ios2 = (struct IOSana2Req *)slipUnit->su_Events.mlh_Head;
  1576.  
  1577.     while(ios2->ios2_Req.io_Message.mn_Node.ln_Succ)
  1578.     {
  1579.         ios2_next = (struct IOSana2Req *)ios2->ios2_Req.io_Message.mn_Node.ln_Succ;
  1580.  
  1581.         /* Are they waiting for any of these events? */
  1582.         if(ios2->ios2_WireError & events)
  1583.         {
  1584.             ios2->ios2_Req.io_Error = 0;
  1585.             ios2->ios2_WireError = events;
  1586.             Remove((struct Node *)ios2);
  1587.             TermIO(ios2,slipDevice);
  1588.         }
  1589.         ios2 = ios2_next;
  1590.     }
  1591.     ReleaseSemaphore(&slipUnit->su_ListLock);
  1592. }
  1593.  
  1594. /*
  1595. ** This routine is called whenever the device needs to
  1596. ** be taken offline.  We return any pending CMD_READ's
  1597. ** or CMD_WRITE's to their senders.
  1598. */
  1599. VOID DoOffline(struct SLIPUnit *slipUnit,
  1600.                struct SLIPDevice *slipDevice)
  1601. {
  1602.     struct IOSana2Req *ios2;
  1603.     struct BufferManagement *bm;
  1604.     ObtainSemaphore(&slipUnit->su_ListLock);
  1605.  
  1606.     bm = (struct BufferManagement *)slipUnit->su_BuffMgmt.mlh_Head;
  1607.     while(bm->bm_Node.mln_Succ)
  1608.     {
  1609.         while(ios2 = (struct IOSana2Req *)RemHead((struct List *)&bm->bm_RxQueue))
  1610.         {
  1611.             ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1612.             ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1613.             TermIO(ios2,slipDevice);
  1614.         }
  1615.         bm = (struct BufferManagement *)bm->bm_Node.mln_Succ;
  1616.     }
  1617.     while(ios2 = (struct IOSana2Req *)GetMsg(slipUnit->su_Tx))
  1618.     {
  1619.         ios2->ios2_Req.io_Error = S2ERR_OUTOFSERVICE;
  1620.         ios2->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1621.         TermIO(ios2,slipDevice);
  1622.     }
  1623.     ReleaseSemaphore(&slipUnit->su_ListLock);
  1624. }
  1625.  
  1626. /*
  1627. ** This routine is called whenever a CMD_WRITE request
  1628. ** has returned from the serial driver.
  1629. */
  1630. VOID ServiceTxPort(struct SLIPUnit *slipUnit,
  1631.                    struct SLIPDevice *slipDevice)
  1632. {
  1633.     struct IOSana2Req *ios2;
  1634.  
  1635.     /* See if our IORequest is busy. If not, check for a pending
  1636.        CMD_WRITE request and send it. */
  1637.  
  1638.     if(CheckIO((struct IORequest *)slipUnit->su_SerTx))
  1639.     {
  1640.         WaitIO((struct IORequest *)slipUnit->su_SerTx);
  1641.         if(ios2 = (struct IOSana2Req *)GetMsg(slipUnit->su_Tx))
  1642.         {
  1643.             SendPacket(ios2, slipUnit, slipDevice);
  1644.             slipUnit->su_Continue =     TRUE;
  1645.         }
  1646.     }
  1647. }
  1648.  
  1649. /*
  1650. ** This routine is called whenever a CMD_READ request
  1651. ** returns from the serial driver.  It decodes the
  1652. ** packet data and tries to build complete packets.
  1653. */
  1654. VOID DoSerial(struct IOExtSer *ioSer,
  1655.               struct SLIPUnit *slipUnit,
  1656.               struct SLIPDevice *slipDevice)
  1657. {
  1658.     UBYTE *rx_ptr,*packet_ptr;
  1659.     UBYTE rx_byte, packet_byte;
  1660.     ULONG length,startptr;
  1661.  
  1662.     startptr = (ULONG)slipUnit->su_RxBuff;
  1663.     packet_ptr = slipUnit->su_RxBuffPtr;
  1664.     rx_ptr = slipUnit->su_RxSLIP;
  1665.  
  1666.     length = ioSer->IOSer.io_Actual;
  1667.  
  1668.     while(length--)
  1669.     {
  1670.         rx_byte = packet_byte = *rx_ptr;
  1671.         rx_ptr++;
  1672.  
  1673.         /* Handle SLIP packet decoding...*/
  1674.         if(slipUnit->su_Escape)
  1675.         {
  1676.             if(rx_byte == SLIP_ESC_ESC)
  1677.                 packet_byte = SLIP_ESC;
  1678.             else if(rx_byte == SLIP_ESC_END)
  1679.                 packet_byte = SLIP_END;
  1680.             else
  1681.                 ReceivedGarbage(slipUnit,slipDevice);   /* This packet may be hosed */
  1682.  
  1683.             slipUnit->su_Escape = FALSE;
  1684.         }
  1685.         else if(rx_byte == SLIP_ESC)
  1686.         {
  1687.             slipUnit->su_Escape = TRUE;
  1688.             continue;
  1689.         }
  1690.         else if(rx_byte == SLIP_END)
  1691.         {
  1692.             GotPacket((ULONG)(packet_ptr - startptr) - 128, slipUnit, slipDevice);
  1693.             packet_ptr = slipUnit->su_RxBuff + 128;
  1694.             continue;
  1695.         }
  1696.         *packet_ptr = packet_byte;
  1697.         packet_ptr++;
  1698.  
  1699.         if(((ULONG)(packet_ptr - startptr) - 128) > slipUnit->su_MTU)
  1700.         {
  1701.             packet_ptr = (UBYTE *)(startptr + 128);
  1702.             PacketOverrun(slipUnit,slipDevice);
  1703.         }
  1704.     }
  1705.     slipUnit->su_RxBuffPtr = packet_ptr;
  1706.  
  1707.     /* Queue up another CMD_READ request...*/
  1708.     QueueSerRequest(slipUnit,slipDevice);
  1709. }
  1710.  
  1711. /*
  1712. ** This routine is called whenever we think we've got
  1713. ** a complete packet to satisfy a CMD_READ request.
  1714. */
  1715. VOID GotPacket(ULONG length,
  1716.                struct SLIPUnit *slipUnit,
  1717.                struct SLIPDevice *slipDevice)
  1718. {
  1719.     struct IOSana2Req *ios2;
  1720.     struct BufferManagement *bm;
  1721.     struct ip *iphdr;
  1722.     UBYTE *hdr;
  1723.     UBYTE type;
  1724.  
  1725.     /* We ignore zero-length packets. These occur
  1726.        in between legal SLIP packets due to the
  1727.        way SLIP packets are framed. */
  1728.  
  1729.     if(length)
  1730.     {
  1731.         PacketReceived(length,slipUnit);
  1732.  
  1733.         /* Check out what type of packet we have. */
  1734.  
  1735.         hdr = (UBYTE *)slipUnit->su_RxBuff + 128;
  1736.         type = hdr[0];
  1737.  
  1738.         if(type & 0x80)     /* Compressed TCP */
  1739.         {
  1740.             type = 0x80;
  1741.         }
  1742.         else
  1743.         {
  1744.             if(type >= 0x70)        /* Uncompressed TCP */
  1745.             {
  1746.                 hdr[0] = type & 0xCF;       /* Fix IP header */
  1747.                 type = 0x70;
  1748.             }
  1749.         }
  1750.         if((type == 0x70) || (type == 0x80))        /* TCP Packet */
  1751.         {
  1752.             if(slipUnit->su_State &     SLIPUF_AUTOCOMP)
  1753.                 slipUnit->su_State |= SLIPUF_MAYCOMPRESS;
  1754.  
  1755.             slipUnit->su_MBuff.m_off = hdr;
  1756.             slipUnit->su_MBuff.m_len = length;
  1757.             length = sl_uncompress_tcp(&slipUnit->su_MBuff.m_off,length,type,&slipUnit->su_SLCompress);
  1758.             hdr = slipUnit->su_MBuff.m_off;
  1759.         }
  1760.         else        /* Just a normal SLIP IP Packet */
  1761.         {
  1762.             hdr = slipUnit->su_RxBuff + 128;
  1763.         }
  1764.         iphdr = (struct ip *)hdr;
  1765.  
  1766.         if(length)
  1767.         {
  1768.             BOOL dropped = TRUE; /* Set to false if at least one protocol stack
  1769.                                   * managed to get the packet.  I don't keep
  1770.                                   * individual statistics for each protocol
  1771.                                   * stack. */
  1772.  
  1773.             ObtainSemaphore(&slipUnit->su_ListLock);
  1774.             bm = (struct BufferManagement *)slipUnit->su_BuffMgmt.mlh_Head;
  1775.  
  1776.             while(bm->bm_Node.mln_Succ)
  1777.             {
  1778.                 if(ios2 = (struct IOSana2Req *)RemHead((struct List *)&bm->bm_RxQueue))
  1779.                 {
  1780.                     /* Make the IO request look like it would if they
  1781.                      * accept the packet. */
  1782.  
  1783.                     ios2->ios2_DataLength = length;         /* Length */
  1784.                     ios2->ios2_PacketType = 2048;        /* IP Packet Type */
  1785.                     *(ULONG *)ios2->ios2_SrcAddr = iphdr->ip_src.s_addr;
  1786.                     *(ULONG *)ios2->ios2_DstAddr = iphdr->ip_dst.s_addr;
  1787.  
  1788.                     /* If they don't want the packet, go on to the next
  1789.                      * protocol stack. */
  1790.  
  1791.                     if((*(HOOK_FUNC)bm->bm_PacketFilterHook->h_Entry)(bm->bm_PacketFilterHook,ios2,hdr))
  1792.                     {
  1793.                         /* Copy the data into the protocol stack's buffer using its
  1794.                            supplied callback routine. */
  1795.  
  1796.                         if((*bm->bm_CopyToBuffer)(ios2->ios2_Data,hdr,length))
  1797.                         {
  1798.                             dropped = FALSE;
  1799.                         }
  1800.                         else
  1801.                         {
  1802.                             ios2->ios2_DataLength = 0;
  1803.                             ios2->ios2_Req.io_Error = S2ERR_NO_RESOURCES;
  1804.                             ios2->ios2_WireError = S2WERR_BUFF_ERROR;
  1805.                             DoEvent(S2EVENT_RX|S2EVENT_BUFF,slipUnit,slipDevice);
  1806.                         }
  1807.                         TermIO(ios2,slipDevice);
  1808.  
  1809.                     }
  1810.                     else /* They didn't want it, so put the IOSana2Req back on the list */
  1811.                     {
  1812.                         AddHead((struct List *)&bm->bm_RxQueue,(struct Node *)ios2);
  1813.                     }
  1814.                 }
  1815.                 bm = (struct BufferManagement *)bm->bm_Node.mln_Succ;
  1816.             }
  1817.             ReleaseSemaphore(&slipUnit->su_ListLock);
  1818.  
  1819.             if(dropped)
  1820.             {
  1821.                 PacketDropped(slipUnit,slipDevice);
  1822.             }
  1823.         }
  1824.     }
  1825.     slipUnit->su_Escape = 0;
  1826. }
  1827.  
  1828. /*
  1829. ** This routine is called whenever we need to
  1830. ** get more data from the serial port.  We first
  1831. ** to a SDCMD_QUERY to see how much data is available,
  1832. ** if any.
  1833. */
  1834. VOID QueueSerRequest(struct SLIPUnit *slipUnit,
  1835.                      struct SLIPDevice *slipDevice)
  1836. {
  1837.     slipUnit->su_SerRx->IOSer.io_Command = SDCMD_QUERY;
  1838.     DoIO((struct IORequest *)slipUnit->su_SerRx);
  1839.  
  1840.     if(slipUnit->su_State & SLIPUF_CD)
  1841.     {
  1842.         if(slipUnit->su_SerRx->io_Status & (1<<5))
  1843.         {
  1844.             /* Oops! We've lost carrier. Go offline. */
  1845.             CloseSerial(slipUnit,slipDevice);
  1846.             DoOffline(slipUnit,slipDevice);
  1847.             DoEvent(S2EVENT_OFFLINE,slipUnit,slipDevice);
  1848.             return;
  1849.         }
  1850.     }
  1851.     slipUnit->su_SerRx->IOSer.io_Command = CMD_READ;
  1852.     slipUnit->su_SerRx->IOSer.io_Data = slipUnit->su_RxSLIP;
  1853.     slipUnit->su_SerRx->IOSer.io_Length = min(slipUnit->su_SerRx->IOSer.io_Actual,slipUnit->su_MTU);
  1854.  
  1855.     /* If the number of bytes available is zero, queue a request
  1856.        for one byte. */
  1857.     if(!slipUnit->su_SerRx->IOSer.io_Length)
  1858.         slipUnit->su_SerRx->IOSer.io_Length = 1;
  1859.  
  1860.     SendIO((struct IORequest *)slipUnit->su_SerRx);
  1861. }
  1862.  
  1863. /*
  1864. ** This is the C entry point for the Unit process.
  1865. ** A6 has been set up by the assembly stub in slip_dev.asm.
  1866. */
  1867.  
  1868. VOID ASM DevProcCEntry(REG(a6) struct SLIPDevice *slipDevice)
  1869. {
  1870.     struct Process *proc;
  1871.     struct SLIPUnit *slipUnit;
  1872.     struct IOExtSer *ioser;
  1873.     struct StartupMessage *sm;
  1874.     struct BufferManagement *bm;
  1875.     struct IOSana2Req *ios2;
  1876.     ULONG waitmask,signals;
  1877.     UBYTE signalbit;
  1878.  
  1879.     /* Find our Process pointer and wait for our startup
  1880.        message to arrive. */
  1881.  
  1882.     proc = (struct Process *)FindTask(0L);
  1883.  
  1884.     WaitPort(&proc->pr_MsgPort);
  1885.  
  1886.     /* Pull the startup message off of our process messageport. */
  1887.     sm = (struct StartupMessage *)GetMsg(&proc->pr_MsgPort);
  1888.  
  1889.     /* Grab our Unit pointer. */
  1890.     slipUnit    = (struct SLIPUnit *)sm->Unit;
  1891.  
  1892.     /* Attempt to allocate a signal bit for our Unit MsgPort. */
  1893.     signalbit = AllocSignal(-1L);
  1894.     if(signalbit != -1)
  1895.     {
  1896.         /* Set up our Unit's MsgPort. */
  1897.         slipUnit->su_Unit.unit_MsgPort.mp_SigBit = signalbit;
  1898.         slipUnit->su_Unit.unit_MsgPort.mp_SigTask =     (struct Task *)proc;
  1899.         slipUnit->su_Unit.unit_MsgPort.mp_Flags = PA_SIGNAL;
  1900.  
  1901.         /* Initialize our list semaphore */
  1902.         InitSemaphore(&slipUnit->su_ListLock);
  1903.  
  1904.         /* Initialize our linked lists. */
  1905.         slipUnit->su_Tx = CreateMsgPort();
  1906.  
  1907.         /* Initialize the serial stuff.  If all goes okay,
  1908.            set slipUnit->su_Proc to pointer to our unit process.
  1909.            This will let the Unit init code know that were
  1910.            are okay. */
  1911.  
  1912.         if(InitSerial(slipUnit,slipDevice) && slipUnit->su_Tx)
  1913.             slipUnit->su_Proc = proc;
  1914.     }
  1915.  
  1916.     /* Reply to our startup message */
  1917.     ReplyMsg((struct Message *)sm);
  1918.  
  1919.     /* Check slipUnit->su_Proc to see if everything went okay up
  1920.        above. */
  1921.     if(slipUnit->su_Proc)
  1922.     {
  1923.         waitmask = (1L<<signalbit) | (1L<<slipUnit->su_RxPort->mp_SigBit) |
  1924.                    (1L<<slipUnit->su_TxPort->mp_SigBit) | (1L<<slipUnit->su_Tx->mp_SigBit)
  1925.                    | SIGBREAKF_CTRL_F;
  1926.  
  1927.         /* Loop...*/
  1928.  
  1929.         while(TRUE)
  1930.         {
  1931.             signals = Wait(waitmask);
  1932.  
  1933.             /* Have we been signaled to shut down? */
  1934.             if(signals & SIGBREAKF_CTRL_F)
  1935.                 break;
  1936.  
  1937.         do
  1938.             {
  1939.                 slipUnit->su_Continue = FALSE;
  1940.  
  1941.                 if(ios2 = (struct IOSana2Req *)GetMsg((struct MsgPort *)slipUnit))
  1942.                 {
  1943.                     slipUnit->su_Continue = TRUE;
  1944.                     PerformIO(ios2,slipDevice);
  1945.                 }
  1946.                 if(ioser = (struct IOExtSer *)GetMsg(slipUnit->su_RxPort))
  1947.                 {
  1948.                     slipUnit->su_Continue = TRUE;
  1949.                     if(slipUnit->su_State & SLIPUF_ONLINE)
  1950.                     {
  1951.                         DoSerial(ioser, slipUnit, slipDevice);
  1952.                     }
  1953.                 }
  1954.                 if(slipUnit->su_State & SLIPUF_ONLINE)
  1955.                 {
  1956.                     ServiceTxPort(slipUnit,slipDevice);
  1957.                 }
  1958.  
  1959.             }
  1960.             while(slipUnit->su_Continue);
  1961.         }
  1962.         /* If we're online, we need to shut everything down. */
  1963.         if(slipUnit->su_State & SLIPUF_ONLINE)
  1964.         {
  1965.             CloseSerial(slipUnit,slipDevice);
  1966.             FreeSignal(signalbit);
  1967.             while(bm = (struct BufferManagement *)RemHead((struct List *)&slipUnit->su_BuffMgmt))
  1968.                 FreeMem(bm,sizeof(struct BufferManagement));
  1969.  
  1970.         }
  1971.         DeinitSerial(slipUnit,slipDevice);
  1972.  
  1973. #ifdef OWNDEVUNIT_SUPPORT
  1974.         if (slipUnit->su_ODUBase)
  1975.             CloseLibrary(slipUnit->su_ODUBase);
  1976. #endif
  1977.         /* Signal the other side we're exiting.  Make sure that
  1978.            we exit before they wake up by using the same trick
  1979.            when replying to Workbench startup messages. */
  1980.  
  1981.         Forbid();
  1982.         Signal((struct Task *)slipUnit->su_Proc,SIGBREAKF_CTRL_F);
  1983.     }
  1984.     /* Something went wrong in the init code.  Drop out. */
  1985.     else
  1986.     {
  1987.         if(signalbit)
  1988.             FreeSignal(signalbit);
  1989.     }
  1990. }
  1991.  
  1992. /* List init routine. */
  1993. VOID NewList(struct List *list)
  1994. {
  1995.     list->lh_Head = (struct Node *)&list->lh_Tail;
  1996.     list->lh_Tail = NULL;
  1997.     list->lh_TailPred = (struct Node *)list;
  1998. }
  1999.